package com.xncoding.freemarker.filter;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

//@Order(3)
//@Component
//@WebFilter(filterName = "traceLogFilter", urlPatterns = "/*")
public class TraceLogFilter implements Filter {
    private static final Logger LOGGER = LoggerFactory.getLogger(TraceLogFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
        String contentType = arg0.getContentType();
        if (!(arg0 instanceof HttpServletRequest) || (contentType != null && contentType.contains("multipart/form-data"))) {
            arg2.doFilter(arg0, arg1);
            return;
        }

        HttpServletRequest req = (HttpServletRequest) arg0;
        FilterRequestWrapper xrw = new FilterRequestWrapper(req);// 防止流读取一次后，Controller无法获取流数据
        System.out.println("traceLogFilter："+JSON.toJSONString(xrw.getBody()));
        arg2.doFilter(xrw, arg1);
    }

    @Override
    public void destroy() {

    }

    class FilterRequestWrapper extends HttpServletRequestWrapper {
        private String body;

        public FilterRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);

            // 读取数据
            StringBuffer sb = new StringBuffer();
            BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
            char[] charBuffer = new char[128];
            int bytesRead = -1;
            while ((bytesRead = br.read(charBuffer)) > 0) {
                sb.append(charBuffer, 0, bytesRead);
            }
            body = sb.toString();
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes("UTF-8"));
            return new ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return bais.read();
                }

                @Override
                public boolean isFinished() {
                    return false;
                }

                @Override
                public boolean isReady() {
                    return false;
                }

                @Override
                public void setReadListener(ReadListener readListener) {

                }
            };
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(this.getInputStream(), StandardCharsets.UTF_8));
        }

        public String getBody() {
            return this.body;
        }
    }
}
